﻿using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace Eniux.Windows.Controls.Core.Core
{
    public   class AttachListView:AttachBase
	{
		public static readonly DependencyProperty CanUserSortColumnsProperty =
			DependencyProperty.RegisterAttached(
				"CanUserSortColumns",
				typeof(bool?),
				typeof(AttachListView),
				new FrameworkPropertyMetadata(null,OnCanUserSortColumnsChanged));

        public static readonly DependencyProperty CanUserSortProperty =
			DependencyProperty.RegisterAttached(
                "CanUserSort",
				typeof(bool?),
				typeof(AttachListView),
                new FrameworkPropertyMetadata(null, OnCanUserSortChanged));

		public static readonly DependencyProperty SortDirectionProperty =
			DependencyProperty.RegisterAttached(
				"SortDirection",
				typeof(ListSortDirection?),
				typeof(AttachListView));

		public static readonly DependencyProperty SortExpressionProperty =
			DependencyProperty.RegisterAttached(
				"SortExpression",
				typeof(string),
				typeof(AttachListView));

        [AttachedPropertyBrowsableForType(typeof(ListView))]
		public static bool? GetCanUserSortColumns(ListView element)
		{
			return (bool?)element.GetValue(CanUserSortColumnsProperty);
		}

        [AttachedPropertyBrowsableForType(typeof(ListView))]
		public static void SetCanUserSortColumns(ListView element, bool? value)
		{
			element.SetValue(CanUserSortColumnsProperty, value);
		}

        //[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
        //public static bool GetCanUserSort(GridViewColumn element)
        //{
        //    return (bool)element.GetValue(CanUserSortProperty);
        //}

        //[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
        //public static void SetCanUserSort(GridViewColumn element, bool value)
        //{
        //    element.SetValue(CanUserSortProperty, value);
        //}

        //[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
        //public static ListSortDirection? GetSortDirection(GridViewColumn element)
        //{
        //    return (ListSortDirection?)element.GetValue(SortDirectionProperty);
        //}

        //[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
        //public static void SetSortDirection(GridViewColumn element, ListSortDirection? value)
        //{
        //    element.SetValue(SortDirectionProperty, value);
        //}

        public static bool? GetCanUserSort(DependencyObject element)
        {
            if (element == null)
                return null;
            return (bool?)element.GetValue(CanUserSortProperty);
        }

        public static void SetCanUserSort(DependencyObject element, bool? value)
        {
            element.SetValue(CanUserSortProperty, value);
        }

        public static ListSortDirection? GetSortDirection(DependencyObject element)
        {
            return (ListSortDirection?)element.GetValue(SortDirectionProperty);
        }

        public static void SetSortDirection(DependencyObject element, ListSortDirection? value)
        {
            element.SetValue(SortDirectionProperty, value);
        }

		[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
		public static string GetSortExpression(GridViewColumn element)
		{
			return (string)element.GetValue(SortExpressionProperty);
		}

		[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
		public static void SetSortExpression(GridViewColumn element, string value)
		{
			element.SetValue(SortExpressionProperty, value);
		}

		private static void OnCanUserSortColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			var listView = (ListView)d;
			if ((bool)e.NewValue)
			{

				listView.AddHandler(GridViewColumnHeader.ClickEvent, (RoutedEventHandler)OnColumnHeaderClick);
				if (listView.IsLoaded)
				{
					DoInitialSort(listView);
				}
				else
				{
					listView.Loaded += OnLoaded;
				}
			}
			else
			{
				listView.RemoveHandler(GridViewColumnHeader.ClickEvent, (RoutedEventHandler)OnColumnHeaderClick);
			}
		}

        private static void OnCanUserSortChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if(d.GetType()==typeof(GridViewColumn))
            {
                GridViewColumn column = (GridViewColumn)d;
                ManageAttachSortFromGridViewColumnProperty(column, (bool)e.NewValue);
            }
        }

		private static void OnLoaded(object sender, RoutedEventArgs e)
		{
			var listView = (ListView)e.Source;
            ManageAttachSortFromListViewProperty(listView, GetCanUserSortColumns(listView));
			listView.Loaded -= OnLoaded;
			DoInitialSort(listView);
		}


        private static void ManageAttachSortFromListViewProperty(ListView listView,bool? _bool)
        {
            GridView gridview = listView.View as GridView;
            Setter set = new Setter(CanUserSortProperty, _bool);
            try
            {
                if (!gridview.ColumnHeaderContainerStyle.Setters.Contains(set))
                {
                    gridview.ColumnHeaderContainerStyle.Setters.Add(set);
                }
                else
                {
                    int i = gridview.ColumnHeaderContainerStyle.Setters.IndexOf(set);
                    (gridview.ColumnHeaderContainerStyle.Setters[i] as Setter).Value = _bool;
                }
            }
            catch (System.Exception)
            {
            }
        }
        private static void ManageAttachSortFromGridViewColumnProperty(GridViewColumn column,bool _bool)
        {
            Setter set = new Setter(CanUserSortProperty, _bool);
            Style style = new Style();
            style.TargetType = typeof(GridViewColumnHeader);
            style.Setters.Add(set);
            if (column.HeaderContainerStyle == null)
                style.BasedOn = Application.Current.FindResource("GridViewColumnHeader_Default") as Style;
            else
                style.BasedOn = column.HeaderContainerStyle;
            column.HeaderContainerStyle = style;
        }
		private static void DoInitialSort(ListView listView)
		{
			var gridView = (GridView)listView.View;
			var column = gridView.Columns.FirstOrDefault(c => GetSortDirection(c) != null);
			if (column != null)
			{
				DoSort(listView, column);
			}
		}

		private static void OnColumnHeaderClick(object sender, RoutedEventArgs e)
		{
			var columnHeader = e.OriginalSource as GridViewColumnHeader;
            
			if (columnHeader != null &&columnHeader.Column!=null)
			{
                bool? b = GetCanUserSort(columnHeader);
                bool _bool = b== null ? false : (bool)b;
                ListView listview = (ListView)e.Source;
                GridView gridview = listview.View as GridView;
                foreach (GridViewColumn column in gridview.Columns)
                {
                    GridViewColumnHeader header = (GridViewColumnHeader)e.OriginalSource;
                    if (column.HeaderContainerStyle != null && column != header.Column)
                    {
                        Setter set = new Setter(SortDirectionProperty, null);
                        Style style = new Style();
                        style.TargetType = typeof(GridViewColumnHeader);
                        style.Setters.Add(set);
                        style.BasedOn = column.HeaderContainerStyle;
                        column.HeaderContainerStyle = style;
                    }
                }

                if(_bool)
				    DoSort((ListView)e.Source, columnHeader.Column);
			}
		}

		private static void DoSort(ListView listView, GridViewColumn newColumn)
		{
			var sortDescriptions = listView.Items.SortDescriptions;
			var newDirection = ListSortDirection.Ascending;

			var propertyPath = ResolveSortExpression(newColumn);
			if (propertyPath != null)
			{
				if (sortDescriptions.Count > 0)
				{
					if (sortDescriptions[0].PropertyName == propertyPath)
					{
						newDirection = GetSortDirection(newColumn) == ListSortDirection.Ascending ?
							ListSortDirection.Descending :
							ListSortDirection.Ascending;
					}
					else
					{
						var gridView = (GridView)listView.View;
						foreach (var column in gridView.Columns.Where(c => GetSortDirection(c) != null))
						{
							SetSortDirection(column, null);
						}
					}

					sortDescriptions.Clear();
				}

                try
                {
                    sortDescriptions.Add(new SortDescription(propertyPath, newDirection));
                }
                catch (System.Exception)
                {
                }
				SetSortDirection(newColumn, newDirection);
                Setter set = new Setter(SortDirectionProperty, newDirection);
                if (newColumn.HeaderContainerStyle != null)
                {
                    if (newColumn.HeaderContainerStyle.Setters.Contains(set))
                    {
                        int i = newColumn.HeaderContainerStyle.Setters.IndexOf(set);
                        (newColumn.HeaderContainerStyle.Setters[i] as Setter).Value = newDirection;
                    }
                    else
                    {
                        Style newstyle = new Style();
                        newstyle.TargetType = typeof(GridViewColumnHeader);
                        newstyle.Setters.Add(set);
                        newstyle.BasedOn = newColumn.HeaderContainerStyle;
                        newColumn.HeaderContainerStyle = newstyle;
                    }
                }
                else
                {
                    Style style = new Style();
                    style.TargetType = typeof(GridViewColumnHeader);
                    style.Setters.Add(set);
                    style.BasedOn = Application.Current.FindResource("GridViewColumnHeader_Default") as Style;
                    newColumn.HeaderContainerStyle = style;
                }
			}
		}

		private static string ResolveSortExpression(GridViewColumn column)
		{
			var propertyPath = GetSortExpression(column);
			if (propertyPath == null)
			{
				var binding = column.DisplayMemberBinding as Binding;
				return binding != null ? binding.Path.Path : null;
			}

			return propertyPath;
		}
	}
}